#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
using namespace std;

//typedef int DataType;
//class Stack
//{
//public:
//	Stack(size_t capacity) // 假设栈不提供默认构造
//	{
//		_array = (DataType*)malloc(capacity * sizeof(DataType));
//		if (nullptr == _array)
//		{
//			perror("malloc申请空间失败");
//			return;
//		}
//		_size = 0;
//		_capacity = capacity;
//	}
//	void Push(const DataType& data)
//	{
//		// CheckCapacity();
//		_array[_size] = data;
//		_size++;
//	}
//	~Stack()
//	{
//		if (_array)
//		{
//			free(_array);
//			_array = nullptr;
//			_capacity = 0;
//			_size = 0;
//		}
//	}
//private:
//	DataType* _array;
//	size_t _size;
//	size_t _capacity;
//};
//
//class MyQueue
//{
//public:
//	// Stack不具备默认构造，这个时候MyQueue也无法生成默认构造
//	// 初始化列表
//	// 初始化列表本质可以理解为每个对象中成员定义
//	
//	// 所有的成员，你可以在初始化列表中初始化，也可以在函数体内初始化
//	// 1、引用 2、const 3、没有默认构造的自定义类型成员(必须显式传参调用构造)
//	MyQueue(int n = 20, int& rr)
//		:_pushst(n)
//		,_popst(n)
//		,_size(0)
//		,_x(1)
//		,_ref(rr)
//	{
//		//_x = 1; // err
//	}
//private:
//	// 声明
//	Stack _pushst;
//	Stack _popst;
//	int _size;
//
//	// 有一些变量必须放在初始化列表
//	const int _x; // 只有一次初始化的机会，即在定义的时候
//	int& _ref; // 同样引用在定义的时候也必须初始化
//};

//int main()
//{
//	int xx = 0;
//	MyQueue q1(10, xx);
//	//MyQueue q2;
//
//	const int y = 1;
//	int& ry = xx;
//
//	return 0;
//}

//class Time
//{
//public:
//	Time(int hour = 0)
//		:_hour(hour)
//	{
//		cout << "Time()" << endl;
//	}
//private:
//	int _hour;
//};
//class Date
//{
//public:
//	Date(int day)
//	{}
//private:
//	int _day;
//	Time _t;
//};
//int main()
//{
//	Date d(1);
//
//	return 0;
//}

//typedef int DataType;
//class Stack
//{
//public:
//	Stack(size_t capacity = 4) // 假设栈不提供默认构造
//	{
//		_array = (DataType*)malloc(capacity * sizeof(DataType));
//		if (nullptr == _array)
//		{
//			perror("malloc申请空间失败");
//			return;
//		}
//		_size = 0;
//		_capacity = capacity;
//	}
//	void Push(const DataType& data)
//	{
//		// CheckCapacity();
//		_array[_size] = data;
//		_size++;
//	}
//	~Stack()
//	{
//		if (_array)
//		{
//			free(_array);
//			_array = nullptr;
//			_capacity = 0;
//			_size = 0;
//		}
//	}
//private:
//	DataType* _array;
//	size_t _size;
//	size_t _capacity;
//};
//
//class MyQueue
//{
//public:
//	// 初始化列表，不管写不写，每个成员变量都会先走一遍
//	// 自定义类型的成员会调用默认构造，没有就报错（没有默认构造就报错）
//	// 内置类型有缺省值用缺省值，没有的话看编译器
//	// 先走初始化列表 + 再走函数体，即使你没写初始化列表
//	// 实践中，尽可能使用初始化列表来初始化，不方便的再使用函数体初始化
//	MyQueue()
//		:_size(1)
//		,_pushst(10)
//		,_ptr((int*)malloc(8))
//	{}
//private:
//	Stack _pushst;
//	Stack _popst;
//
//	// 缺省值，给初始化列表用的
//	int _size = 0;
//	int* _ptr;
//};
//
//int main()
//{
//	MyQueue q;
//
//	return 0;
//}

//class A
//{
//public:
//	A(int a)
//		// 成员变量在类中的声明次序就是其在初始化列表中的初始化顺序
//		// 与其在初始化列表中的先后次序无关
//		// 所以我们尽量保持声明顺序和初始化顺序一致
//		:_a1(a)
//		,_a2(_a1)
//	{}
//
//	void Print() {
//		cout << _a1 << " " << _a2 << endl;
//	}
//private:
//	int _a2;
//	int _a1;
//};
//
//int main() {
//	A aa(1);
//	aa.Print();
//
//	return 0;
//}

//class A
//{
//public:
//	// 单参数构造函数支持隐式类型转换
//	A(int a)
//		:_a(a)
//	{
//		cout << "A(int a)" << endl;
//	}
//
//	A(const A& aa)
//		:_a(aa._a)
//	{
//		cout << "A(const A& aa)" << endl;
//	}
//private:
//	int _a;
//};
//
//int main()
//{
//	A aa1(1);
//	// 拷贝构造
//	A aa2 = aa1;
//
//	// 隐式类型转换
//	// 内置类型转换为自定义类型
//	// 可以用3赋值一个临时变量，然后再拷贝构造
//	// 用3构造一个A的临时对象，再用这个临时对象拷贝构造aa3
//	// 编译器遇到连续构造 + 拷贝构造 -> 优化为直接构造
//	A aa3 = 3; // 本来先用3来构造，再赋值构造，编译器又觉得浪费
//	A aa4 = 3.3;
//
//	// raa引用的是类型转换中用3构造的临时对象
//	const A& raa = 3;
//
//	return 0;
//}


//class A
//{
//public:
//	A() { ++_scount; }
//	A(const A& t) { ++_scount; }
//	~A() { --_scount; }
//	static int GetACount() { return _scount; }
//private:
//	static int _scount;
//};
//int A::_scount = 0;
//void TestA()
//{
//	cout << A::GetACount() << endl;
//	A a1, a2;
//	A a3(a1);
//	cout << A::GetACount() << endl;
//}

//class A
//{
//public:
//	// 单参数构造函数支持隐式类型转换
//	// 如果不想让转换发生，那就加关键字explicit
//	// explicit A(int a)
//	A(int a)
//		:_a(a)
//	{
//		cout << "A(int a)" << endl;
//	}
//
//	// 多参数构造函数也支持，用花括号括起来即可
//	A(int a1, int a2)
//		:_a(0)
//		,_a1(a1)
//		,_a2(a2)
//	{
//		cout << "A(int a1, int a2)" << endl;
//	}
//
//	A(const A& aa)
//		:_a(aa._a)
//	{
//		cout << "A(const A& aa)" << endl;
//	}
//private:
//	int _a;
//	int _a1;
//	int _a2;
//};

//class Stack
//{
//public:
//	void Push(const A& aa)
//	{
//		// ...
//	}
//
//	// ...
//};

//int main()
//{
//	Stack st;
//
//	//// 方法一
//	//A a1(1);
//	//st.Push(a1);
//
//	//// 方法二
//	//st.Push(2); // 因为是2构造的常性临时变量，所以Push函数里面要加const修饰
//
//	//// 显然方法二更方便一点
//
//	A aaa1(1, 2);
//	// A aaa2 = (1, 2); // err，逗号表达式
//	const A& aaa2 = { 1, 2 }; // right
//
//	return 0;
//}

//class BB
//{
//private:
//	// 缺省值
//  // 声明，是给初始化列表的
//	int _b1 = 1;
//	int* _ptr = (int*)malloc(40);
//	Stack _pushst = 10;
//	A _a1 = 1;
//	A _a2 = { 1, 2 };
//};
//
//class A
//{
//public:
//	// 静态成员函数没有隐藏的this指针，不能访问任何非静态成员
//	// 静态成员也是类的成员，受public、protected、private 访问限定符的限制
//	A() { ++_scount; }
//	A(const A& t) { ++_scount; }
//	~A() { --_scount; }
//
//	// 没有this指针，只能访问静态成员
//	static int GetACount() { return _scount; }
//private:
//	int _a1;
//	int _a2;
//
//	// 在静态区，不存在对象中，对象只存成员变量
//	// 静态成员变量一定要在类外进行初始化
//	// 不能给缺省值，这是在初始化列表中的
//	// 他在静态区不在对象中，不走初始化列表
//	// 意义就在于它属于整个类，属于所有对象
//public:
//
//	static int _scount;
//};
//
//// 定义
//int A::_scount = 0;
//
//void TestA()
//{
//	cout << A::GetACount() << endl;
//	A a1, a2;
//	A a3(a1);
//	cout << A::GetACount() << endl;
//}
//
//int main()
//{
//	A aa1;
//	cout << sizeof(aa1) << endl;
//
//	//aa1._scount++;
//	//cout << A::_scount << endl;
//
//	A aa2(aa1);
//	A aa3 = aa1;
//
//	// 一个实际运用场景就是判断A类型的对象实时还有几个
//	cout << A::_scount << endl;
//	cout << A::GetACount() << endl;
//	
//	return 0;
//}

//class Sum
//{
//public:
//	Sum()
//	{
//		_ret += _i;
//		++_i;
//	}
//
//	static int GetRet() { return _ret; }
//private:
//	static int _i;
//	static int _ret;
//};
//
//int Sum::_i = 1;
//int Sum::_ret = 0;
//
//class Solution
//{
//public:
//	int Sum_Solution(int n)
//	{
//		Sum s[n];
//
//		return Sum::GetRet();
//	}
//};
//
//int main()
//{
//	Solution sol;
//	cout << sol.Sum_Solution(2) << endl;
//
//	return 0;
//}


//// 友元
//// 友元提供了一种突破封装的方式，但是增加了耦合度
//// 友元是单向的
//class Time
//{
//	// 声明日期类为时间类的友元类
//	// 日期类中就直接访问Time类中的私有成员变量
//	friend class Date; 
//public:
//	Time(int hour = 0, int minute = 0, int second = 0)
//		: _hour(hour)
//		, _minute(minute)
//		, _second(second)
//	{}
//private:
//	int _hour;
//	int _minute;
//	int _second;
//};
//
//class Date
//{
//public:
//	Date(int year = 1900, int month = 1, int day = 1)
//		: _year(year)
//		, _month(month)
//		, _day(day)
//	{}
//
//	void SetTimeOfDate(int hour, int minute, int second)
//	{
//		// 直接访问时间类私有的成员变量
//		_t._hour = hour;
//		_t._minute = minute;
//		_t._second = second;
//	}
//
//private:
//	int _year;
//	int _month;
//	int _day;
//	Time _t;
//};

// 内部类

//class A
//{
//private:
//	static int k;
//	int h;
//public:
//	// 即使放在里面，B也是一个独立的类，只是收到了域的限制
//	class B // B天生就是A的友元
//	{
//	public:
//		void foo(const A& a)
//		{
//			cout << k << endl;//OK
//			cout << a.h << endl;//OK
//		}
//	};
//};
//int A::k = 1;
//
//int main()
//{
//	cout << sizeof(A) << endl; // 跟类B没有任何关系
//	A::B b;
//	b.foo(A());
//
//	return 0;
//}

// 匿名对象
//class A
//{
//public:
//	A(int a = 0)
//		:_a(a)
//	{
//		cout << "A(int a)" << endl;
//	}
//	~A()
//	{
//		cout << "~A()" << endl;
//	}
//private:
//	int _a;
//};
//
//class Solution {
//public:
//	int Sum_Solution(int n) {
//		//...
//		return n;
//	}
//};
//int main()
//
//{
//	A aa1;
//	// 不能这么定义对象，因为编译器⽆法识别下⾯是⼀个函数声明，还是对象定义
//	//A aa1();
//	// 但是我们可以这么定义匿名对象，匿名对象的特点不⽤取名字，
//	// 但是他的⽣命周期只有这⼀⾏，我们可以看到下⼀⾏他就会⾃动调⽤析构函数
//	A();
//	A(1);
//	A aa2(2);
//
//	Solution s1;
//	s1.Sum_Solution(10);
//
//	// 匿名对象在这样场景下就很好⽤，当然还有⼀些其他使⽤场景，这个我们以后遇到了再说
//	Solution().Sum_Solution(10);
//
//	return 0;
//}

// 局部的静态第一次调用时构造初始化
// 全局对象，在main函数之前构造
// 先定义后析构，后定义先析构

